﻿using Crap4Net;
using System;
using NUnit.Framework;
using Crap4Net.CCParsers;
using System.Collections.Generic;

namespace Crap4Net.UnitTests.CCParsersTests
{


    [TestFixture]
    public class ReflectorParserTests
    {
        private const string  REFLECTOR_FILE_PATH = @"UnitTestData\ReflectorFiles\";
        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        
        [Test()]
        [ExpectedException(typeof(ApplicationException))]
        public void Data_FileNotLoaded_ThrowsException()
        {
            var target = new ReflectorParser();
            var dummy = target.Data;
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void LoadData_InvalidFileName_throwsException()
        {
            var target = new ReflectorParser();
            target.LoadData("NoSuchFile.xml");
        }

        [Test]
        public void Data_ctor_CorrectMethodName()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "ctor.xml");

            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("unknown", "dummyProject", "Class1", ".ctor", new string[] { }), 
                1 );
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_EmptyClass_CtorIsAdded()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "EmptyClass.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("unknown", "dummyProject", "class2", ".ctor", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_GenericMethod_CorrectNameIsParsed()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "GenericMethod.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("unknown", "dummyProject", "Class1", "GenericMethod<T>", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_OverLoadedMethod_AllVariantsAreParsed()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "OverloadedMethod.xml");

            var actual = target.Data;

            var expected = new List<CCDataEntry>(){
                new CCDataEntry(
                    new MethodSignature("unknown", "dummyProject", "Class1", "method2", new string[] { }),
                    1),
                new CCDataEntry(
                    new MethodSignature("unknown", "dummyProject", "Class1", "method2", new string[] { "Int32"}),
                    1),
                new CCDataEntry(
                    new MethodSignature("unknown", "dummyProject", "Class1", "method2", new string[] { "Single"}),
                    1),
                new CCDataEntry(
                    new MethodSignature("unknown", "dummyProject", "Class1", "method2", new string[] { "Double"}),
                    1)
            };
            CollectionAssert.AreEquivalent(expected, actual);
        }

        [Test]
        public void Data_Property_SetAndGetAreParsed()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "Property.xml");
            var actual = target.Data;
            var expectedGet = new CCDataEntry(
                new MethodSignature("unknown", "dummyProject", "Class1", "get_SomeProperty", new string[] { }),
                1);
            var expectedSet = new CCDataEntry(
                new MethodSignature("unknown", "dummyProject", "Class1", "set_SomeProperty", new string[] {"Object" }),
                1);
            CollectionAssert.Contains(actual, expectedGet);
            CollectionAssert.Contains(actual, expectedSet);

        }

        [Test]
        public void Data_cctor_CorrectMaethodNameIsParsed()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "StaticCtor.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("unknown", "dummyProject", "Class1", ".cctor", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);

        }

        [Test]
        public void Data_StaticMethod_IsParsedCorrectly()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "StaticMethod.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("unknown", "dummyProject", "Class1", "staticMethod", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);
        }

        //[Test]
        //public void Data_AnonymousType_IsParsedCorrectly()
        //{
        //    var target = new ReflectorParser();
        //    target.LoadData(REFLECTOR_FILE_PATH + "AnonymousType.xml");
        //    var actual = target.Data;

        //    var typename = "<>f__AnonymousType0<<Method>j__TPar,<Complexity>j__TPar>";
        //    var expected = new List<CCDataEntry>(){
        //        new CCDataEntry(
        //            new MethodSignature("unknown", "", typename, ".ctor", new string[] { }),
        //            1),
        //        //new CCDataEntry(
        //        //    new MethodSignature("unknown", "", typename, "get_Method", new string[] { }),
        //        //    1),
        //        //new CCDataEntry(
        //        //    new MethodSignature("unknown", "", typename, "get_Complexity", new string[] { }),
        //        //    1),
        //        //new CCDataEntry(
        //        //    new MethodSignature("unknown", "", typename, "ToString", new string[] { }),
        //        //    1),
        //        //new CCDataEntry(
        //        //    new MethodSignature("unknown", "", typename, "Equals", new string[] { }),
        //        //    3),
        //        //new CCDataEntry(
        //        //    new MethodSignature("unknown", "", typename, "GetHashCode", new string[] { }),
        //        //    1)
        //    };
        //    CollectionAssert.IsSubsetOf(expected, actual);
        //    //CollectionAssert.AreEquivalent(expected, actual);

        //}

        [Test]
        public void Data_TypeWithoutNameSpace_IsParsedCorrectly()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "NoNameSpace.xml");

            var actual = target.Data;

            var expected = new List<CCDataEntry>(){
                new CCDataEntry(
                    new MethodSignature("unknown", "", "ClassWithNoNameSpace", ".ctor", new string[] { }),
                    1),
                new CCDataEntry(
                    new MethodSignature("unknown", "", "ClassWithNoNameSpace", "StameMethod", new string[] { }),
                    1)
            };
            CollectionAssert.AreEquivalent(expected, actual);
        }

        [Test]
        public void Data_TypeWithComplexNameSpace_IsParsedCorrectly()
        {
            var target = new ReflectorParser();
            target.LoadData(REFLECTOR_FILE_PATH + "ComplexNameSpace.xml");

            var actual = target.Data;

            var expected = new List<CCDataEntry>(){
                new CCDataEntry(
                    new MethodSignature("unknown", "NameSpace1.NameSpace2", "ClassName", ".ctor", new string[] { }),
                    1),
                new CCDataEntry(
                    new MethodSignature("unknown", "NameSpace1.NameSpace2", "ClassName", "StameMethod", new string[] { }),
                    1)
            };
            CollectionAssert.AreEquivalent(expected, actual);
        }

        //[Test]
        //[Ignore]
        //public void Data_OverLoad_RetrievesCorrectData()
        //{
        //    var target = new ReflectorParser();
        //    target.LoadData(REFLECTOR_FILE_PATH + "FullReport.xml");
        //    var actual = target.Data;

        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", ".ctor", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method1", 2)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2(Int32)", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2(Double)", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2(Single)", 1)));
        //    Assert.AreEqual(6, actual.Count);
        //}

        //[Test]
        //[Ignore]
        //public void Data_ValidFile_RetrievesCorrectData()
        //{
        //    var target = new ReflectorParser();
        //    target.LoadData(REFLECTOR_FILE_PATH + "ReflectorCCReport.xml");
        //    var actual = target.Data;

        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", ".ctor", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method1", 2)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2(Int32)", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2(Double)", 1)));
        //    Assert.IsTrue(actual.Contains(new CCDataEntry("Class1", "method2(Single)", 1)));
        //    Assert.AreEqual(6, actual.Count);
        //}

        [Test]
        public void LoadData_FileFromRealUser_DoesNotCrash()
        {
            var target = new ReflectorParser();

            target.LoadData(REFLECTOR_FILE_PATH + "crap.xml");
            var actual = target.Data;

        }

    }
}
